/*
 MIT License
 
 Copyright (c) 2021 Steven Le

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
 
 The above copyright notice and this permission notice shall be included in all
 copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
*/

/*
 *	utmplib.c  - functions to buffer reads from utmp file
 * 	
 * 	functions are
 *		utmp_open(filename) 	- open file
 *			returns -1 on error 
 * 		utmp_next() 		- return pointer to next stack
 * 			returns NULL on EOF
 * 		utmp_close() 		- close file
 * 		
 * 	reads NRECS per read and then doles from out from the buffer
 */
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <utmp.h>

#define NRECS 		16
#define NULLUT 		(struct utmp *)NULL
#define UTSIZE 		sizeof(struct utmp)

static char 	utmpbuf[NRECS * UTSIZE];		/* storage */
static int 	num_recs;				/* numstored */
static int 	cur_recs;				/* next to go */
static int 	fd_utmp = -1;				/* read from */

/* -- declaration start --*/
int utmp_open(char *); 
struct utmp* utmp_next(); 
int utmp_reload();
int utmp_close();
/* -- declaration end--*/


int utmp_open(char *filename)
{
	fd_utmp = open(filename, O_RDONLY);		/* open it */
	cur_recs = num_recs = 0; 			/* no recs yet  */
	return fd_utmp;					/* report */
}

struct utmp* utmp_next()
{
	struct utmp *recp;				/* error ? */
	if (fd_utmp == -1) 
		return NULLUT;
	if (cur_recs == num_recs && utmp_reload() == 0) /* get address of next record  */
	{
		return NULLUT;
	}
	recp = (struct utmp*) &utmpbuf[cur_recs * UTSIZE];
	cur_recs++;
	return recp;
}

int utmp_reload()
/*
 *	read next bunch of records into buffer
 */ 
{
	int amt_read;					 /* read them in */
	amt_read = read(fd_utmp, utmpbuf, NRECS * UTSIZE); /* how many did we get */	
	num_recs = amt_read / UTSIZE; 			/* reset pointer */	       
	cur_recs = 0;

	return num_recs ; 
}

int utmp_close()
{
	if(fd_utmp != -1)				/* don't close if not */
	close (fd_utmp);				/* open */
}


